package han.yang.service.friendship.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import han.yang.common.ResponseVO;
import han.yang.common.enums.AllowFriendTypeEnum;
import han.yang.common.enums.CheckFriendShipTypeEnum;
import han.yang.common.enums.FriendShipErrorCode;
import han.yang.common.enums.FriendShipStatusEnum;
import han.yang.common.exception.ApplicationException;
import han.yang.common.model.RequestBase;
import han.yang.service.friendship.dao.ImFriendShipEntity;
import han.yang.service.friendship.dao.ImFriendShipRequestEntity;
import han.yang.service.friendship.dao.mapper.ImFriendShipMapper;
import han.yang.service.friendship.model.dto.FriendDto;
import han.yang.service.friendship.model.req.*;
import han.yang.service.friendship.model.resp.CheckFriendShipResp;
import han.yang.service.friendship.model.resp.ImportFriendShipResp;
import han.yang.service.friendship.service.ImFriendService;
import han.yang.service.friendship.service.ImFriendShipRequestService;
import han.yang.service.user.dao.ImUserDataEntity;
import han.yang.service.user.service.ImUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 好友信息的CRUD
 * @author yanghan
 * @date 2023/2/25
 */
@Service
public class ImFriendServiceImpl implements ImFriendService {

    @Resource
    ImFriendShipMapper imFriendShipMapper;

    @Resource
    ImUserService imUserService;

    @Resource
    ImFriendShipRequestService imFriendShipRequestService;

    /**
     * limitSize 批量操作的限制次数
     */
    private final int limitSize = 100;

    @Override
    public ResponseVO<?> importFriendShip(ImportFriendShipReq req) {
        if (req.getFriendItem().size() > limitSize){
            return ResponseVO.errorResponse(FriendShipErrorCode.IMPORT_SIZE_BEYOND);
        }
        ImportFriendShipResp resp = new ImportFriendShipResp();
        List<String> successId = new ArrayList<>();
        List<String> errorId = new ArrayList<>();
        for (ImportFriendShipReq.ImportFriendDto dto : req.getFriendItem()) {
            ImFriendShipEntity entity = new ImFriendShipEntity();
            entity.setToId(dto.getToId());
            entity.setRemark(dto.getRemark());
            entity.setAddSource(dto.getAddSource());
            entity.setStatus(dto.getStatus());
            entity.setBlack(dto.getBlack());
            entity.setAppId(req.getAppId());
            entity.setFromId(req.getFromId());
            try {
                int insert = imFriendShipMapper.insert(entity);
                if (insert == 1){
                    successId.add(entity.getToId());
                }else {
                    errorId.add(entity.getToId());
                }
            }catch (Exception e){
                errorId.add(entity.getToId());
            }
        }
        resp.setErrorId(errorId);
        resp.setSuccessId(successId);
        return ResponseVO.successResponse(resp);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseVO<?> addFriend(AddFriendReq req) {
        // 查询当前用户的信息
        ResponseVO<ImUserDataEntity> fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId());
        // 当前用户不存在
        if(!fromInfo.isOk()){
            return fromInfo;
        }
        // 查询需要添加的好友的信息
        ResponseVO<ImUserDataEntity> toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId());
        if(!toInfo.isOk()){
            return toInfo;
        }
        if (toInfo.getData().getFriendAllowType() != null && toInfo.getData().getFriendAllowType() == AllowFriendTypeEnum.NOT_NEED.getCode()){
            // 无需验证，直接添加好友
            return doAddFriend(req,req.getFromId(), req.getAppId(), req.getToItem());
        }else {
            // TODO 申请逻辑 消息队列发送好友申请
            // 验证两者是否已经是好友
            QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
            query.eq("app_id",req.getAppId());
            query.eq("from_id",req.getFromId());
            query.eq("to_id",req.getToItem().getToId());
            ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query);
            if (fromItem == null || fromItem.getStatus() != FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){
                // 在好友申请表插入一条申请记录
                return imFriendShipRequestService.addFriendShipRequest(req.getFromId(),
                        req.getToItem(),
                        req.getAppId());
            }else {
                return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseVO<?> updateFriend(UpdateFriendReq req) {
        // 查询当前用户的信息
        ResponseVO<ImUserDataEntity> fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId());
        // 当前用户不存在
        if(!fromInfo.isOk()){
            return fromInfo;
        }
        // 查询需要添加的好友的信息
        ResponseVO<ImUserDataEntity> toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId());
        if(!toInfo.isOk()){
            return toInfo;
        }
        return doUpdateFriend(req.getFromId(), req.getAppId(),req.getToItem());
    }

    @Override
    public ResponseVO<?> deleteFriend(DeleteFriendReq req) {
        QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
        query.eq("app_id",req.getAppId());
        query.eq("from_id",req.getFromId());
        query.eq("to_id",req.getToId());
        ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query);
        if (fromItem == null){
            return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_NOT_YOUR_FRIEND);
        }else {
            if (fromItem.getStatus().equals(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode())){
                // 执行删除
                UpdateWrapper<ImFriendShipEntity> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda().set(ImFriendShipEntity::getStatus,FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode())
                        .eq(ImFriendShipEntity::getAppId,req.getAppId())
                        .eq(ImFriendShipEntity::getToId,req.getToId())
                        .eq(ImFriendShipEntity::getFromId,req.getFromId());
                try {
                    int update = imFriendShipMapper.update(null, updateWrapper);
                    if (update == 1){
                        return ResponseVO.successResponse();
                    }else {
                        return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_DATA_UPDATE_ERROR);
                    }
                }catch (Exception e){
                    throw new ApplicationException(FriendShipErrorCode.FRIEND_DATA_UPDATE_ERROR);
                }
            }else {
                return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_DELETED);
            }
        }
    }

    @Override
    public ResponseVO<?> deleteAllFriend(DeleteFriendReq req) {
        UpdateWrapper<ImFriendShipEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(ImFriendShipEntity::getStatus,FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode())
                .eq(ImFriendShipEntity::getAppId,req.getAppId())
                .eq(ImFriendShipEntity::getFromId,req.getFromId())
                .eq(ImFriendShipEntity::getStatus,FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
        try {
            imFriendShipMapper.update(null, updateWrapper);
            return ResponseVO.successResponse();
        }catch (Exception e){
            throw new ApplicationException(FriendShipErrorCode.FRIEND_DATA_UPDATE_ERROR);
        }
    }

    @Override
    public ResponseVO<?> getAllFriendShip(GetAllFriendShipReq req) {
        QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
        query.eq("app_id",req.getAppId());
        query.eq("from_id",req.getFromId());
        return ResponseVO.successResponse(imFriendShipMapper.selectList(query).stream().filter(item->item.getStatus().equals(1)));
    }

    @Override
    public ResponseVO<?> getRelation(GetRelationReq req) {
        QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
        query.eq("app_id",req.getAppId());
        query.eq("from_id",req.getFromId());
        query.eq("to_id",req.getToId());
        ImFriendShipEntity entity = imFriendShipMapper.selectOne(query);
        if(entity == null){
            return ResponseVO.errorResponse(FriendShipErrorCode.REPEATSHIP_IS_NOT_EXIST);
        }
        return ResponseVO.successResponse(entity);
    }

    @Override
    public ResponseVO checkFriendship(CheckFriendShipReq req) {
        List<CheckFriendShipResp> resp;
        if (req.getCheckType().equals(CheckFriendShipTypeEnum.SINGLE.getType())){
            resp = imFriendShipMapper.checkFriendShip(req);
        }else {
            resp = imFriendShipMapper.checkFriendShipBoth(req);
        }
        // resp转为map 方便查询
        Map<String, Integer> collect = resp.stream().collect(Collectors.toMap(CheckFriendShipResp::getToId, CheckFriendShipResp::getStatus));
        // 封装非好友关系的查询
        List<CheckFriendShipResp> finalResp = resp;
        req.getToIds().forEach(info -> {
            if (!collect.containsKey(info)){
                finalResp.add(new CheckFriendShipResp(req.getFromId(),info,0));
            }
        });
        return ResponseVO.successResponse(finalResp);
    }

    @Override
    public ResponseVO addBlack(AddFriendShipBlackReq req) {
        // 检查需要添加黑名单的人是否存在
        ResponseVO<ImUserDataEntity> toInfo = imUserService.getSingleUserInfo(req.getToId(), req.getAppId());
        if(!toInfo.isOk()){
            return toInfo;
        }
        // 查询fromId与toId是否为好友
        QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
        query.eq("app_id",req.getAppId());
        query.eq("from_id",req.getFromId());
        query.eq("to_id",req.getToId());
        ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query);
        if (fromItem == null){
            // 不是好友，则需要执行添加逻辑
            fromItem = new ImFriendShipEntity();
            fromItem.setFromId(req.getFromId());
            fromItem.setToId(req.getToId());
            fromItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode());
            fromItem.setAppId(req.getAppId());
            fromItem.setCreateTime(System.currentTimeMillis());
            int insert = imFriendShipMapper.insert(fromItem);
            if(insert != 1){
                return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR);
            }
        }else {
            // 已经是好友，则直接修改好友状态
            if (fromItem.getStatus() != null && fromItem.getStatus().equals(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode())){
                return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_BLACK);
            }else {
                UpdateWrapper<ImFriendShipEntity> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda()
                        .set(ImFriendShipEntity::getBlack,FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode())
                        .eq(ImFriendShipEntity::getAppId,req.getAppId())
                        .eq(ImFriendShipEntity::getToId,req.getToId())
                        .eq(ImFriendShipEntity::getFromId,req.getFromId());
                int update = imFriendShipMapper.update(null, updateWrapper);
                if (update != 1){
                    return ResponseVO.errorResponse(FriendShipErrorCode.ADD_BLACK_ERROR);
                }
            }
        }
        return ResponseVO.successResponse();
    }

    @Override
    public ResponseVO deleteBlack(DeleteBlackReq req) {
        // 获取好友关系
        QueryWrapper queryFrom = new QueryWrapper<>()
                .eq("from_id", req.getFromId())
                .eq("app_id", req.getAppId())
                .eq("to_id", req.getToId());
        ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(queryFrom);
        // 如果已经不是黑名单成员则返回
        if (fromItem.getBlack() != null && fromItem.getBlack() == FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()) {
            throw new ApplicationException(FriendShipErrorCode.FRIEND_IS_NOT_YOUR_BLACK);
        }
        ImFriendShipEntity update = new ImFriendShipEntity();
        update.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode());
        imFriendShipMapper.update(update, queryFrom);
        return ResponseVO.successResponse();
    }

    @Override
    public ResponseVO checkBlack(CheckFriendShipReq req) {
        List<CheckFriendShipResp> resp;
        if (req.getCheckType() == CheckFriendShipTypeEnum.SINGLE.getType()) {
            resp = imFriendShipMapper.checkFriendShipBlack(req);
        } else {
            resp = imFriendShipMapper.checkFriendShipBlackBoth(req);
        }
        // resp转为map 方便查询
        Map<String, Integer> collect = resp.stream().collect(Collectors.toMap(CheckFriendShipResp::getToId, CheckFriendShipResp::getStatus));
        // 封装非好友关系的查询
        List<CheckFriendShipResp> finalResp = resp;
        req.getToIds().forEach(info -> {
            if (!collect.containsKey(info)){
                finalResp.add(new CheckFriendShipResp(req.getFromId(),info,0));
            }
        });
        return ResponseVO.successResponse(finalResp);
    }

    /*
    note: https://blog.csdn.net/NoviceZ/article/details/128284424
    方法A和方法B在同一类中
        如果A加了@Transaction注解，B上有没有@Transaction注解，事务都是有效的，则AB在同一个事务中。
        如果A不加@Transaction注解，B上有没有@Transaction注解，事务都是无效的。
    如果A和B两个方法不在同一个类中
        如果A加了@Transaction注解，B上有没有@Transaction注解，事务都是有效的。
        如果A不加@Transaction注解，B加了@Transaction注解，只有B是有事务的。
        如果A不加@Transaction注解，B也不加@Transaction注解，A和B都是没有事务的。
     */

    public ResponseVO<?> doAddFriend(RequestBase req, String fromId, Integer appId, FriendDto dto){
        // A - B
        // 在friend表中插入A B两条记录
        // 首先查询记录是否存在，如果存在则判断状态，如果是已添加，则提示已添加，否则修改状态
        // TODO 后续添加拉黑逻辑，A添加B，如果B拉黑了A，则A无法添加
        QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
        query.eq("app_id",appId);
        query.eq("from_id",fromId);
        query.eq("to_id",dto.getToId());
        // 查询出from和to之间好友关系
        ImFriendShipEntity entity = imFriendShipMapper.selectOne(query);
        if (entity == null){
            // 不存在好友关系,添加好友
            entity = new ImFriendShipEntity();
            entity.setFromId(fromId);
            entity.setAppId(appId);
            entity.setToId(dto.getToId());
            entity.setRemark(dto.getRemark());
            entity.setAddSource(dto.getAddSource());
            entity.setExtra(dto.getExtra());
            entity.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
            entity.setCreateTime(System.currentTimeMillis());
            try {
                int insert = imFriendShipMapper.insert(entity);
                if(insert != 1){
                    return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR);
                }
            }catch (Exception e){
                throw new ApplicationException(FriendShipErrorCode.ADD_FRIEND_ERROR);
            }
        }else {
            //如果存在则判断状态，如果是已添加，则提示已添加，如果是未添加，则修改状态
            if (entity.getStatus().equals(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode())){
                // 已经是好友关系
                return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND);
            }
            if (entity.getStatus().equals(FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode())){
                // 状态为已删除,则修改为添加状态
                entity.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
                entity.setRemark(dto.getRemark());
                entity.setAddSource(dto.getAddSource());
                entity.setExtra(dto.getExtra());
                try {
                    imFriendShipMapper.update(entity,query);
                }catch (Exception e){
                    throw new ApplicationException(FriendShipErrorCode.ADD_FRIEND_ERROR);
                }
            }
        }
        // 添加B - A 好友记录
        QueryWrapper<ImFriendShipEntity> toQuery = new QueryWrapper<>();
        toQuery.eq("app_id",appId);
        toQuery.eq("from_id",dto.getToId());
        toQuery.eq("to_id",fromId);
        ImFriendShipEntity toItem = imFriendShipMapper.selectOne(toQuery);
        if(toItem == null){
            toItem = new ImFriendShipEntity();
            toItem.setAppId(appId);
            toItem.setFromId(dto.getToId());
            BeanUtils.copyProperties(dto,toItem);
            toItem.setToId(fromId);
            toItem.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
            toItem.setCreateTime(System.currentTimeMillis());
//            toItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode());
            imFriendShipMapper.insert(toItem);
        }else{
            if(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode() != toItem.getStatus()){
                ImFriendShipEntity update = new ImFriendShipEntity();
                update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
                imFriendShipMapper.update(update,toQuery);
            }
        }
        return ResponseVO.successResponse();
    }

    public ResponseVO<?> doUpdateFriend(String fromId, Integer appId, FriendDto dto){
        UpdateWrapper<ImFriendShipEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(ImFriendShipEntity::getAddSource,dto.getAddSource())
                .set(ImFriendShipEntity::getExtra,dto.getExtra())
                .set(ImFriendShipEntity::getRemark,dto.getRemark())
                .eq(ImFriendShipEntity::getAppId,appId)
                .eq(ImFriendShipEntity::getToId,dto.getToId())
                .eq(ImFriendShipEntity::getFromId,fromId);
        try {
            int update = imFriendShipMapper.update(null, updateWrapper);
            if (update == 1){
                return ResponseVO.successResponse();
            }else {
                return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_DATA_UPDATE_ERROR);
            }
        }catch (Exception e){
            throw new ApplicationException(FriendShipErrorCode.FRIEND_DATA_UPDATE_ERROR);
        }
    }
}
